package open.tech.dawn.rest.module.system.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import open.tech.dawn.core.error.ServiceException;
import open.tech.dawn.rest.common.Const;
import open.tech.dawn.rest.common.annot.Menu;
import open.tech.dawn.rest.common.page.PageFactory;
import open.tech.dawn.rest.common.page.PageInfo;
import open.tech.dawn.rest.module.system.entity.MenuNode;
import open.tech.dawn.rest.module.system.entity.ZTreeNode;
import open.tech.dawn.rest.module.system.enums.MenuStatus;
import open.tech.dawn.rest.module.system.enums.YesOrNotEnum;
import open.tech.dawn.rest.module.system.model.SysMenu;
import open.tech.dawn.rest.module.system.query.MenuQuery;
import open.tech.dawn.rest.module.system.service.ISysMenuService;
import open.tech.dawn.rest.module.system.service.ISysRoleService;
import open.tech.dawn.rest.module.system.service.ISysUserService;
import open.tech.dawn.web.core.aop.Permission;
import open.tech.dawn.web.core.controller.BaseController;
import open.tech.dawn.web.core.support.Result;
import open.tech.dawn.web.util.ToolUtil;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 菜单表 前端控制器
 * </p>
 *
 * @author joss
 * @since 2019-11-07
 */
@RestController
@RequestMapping("/system/sysMenu")
@Menu(name = "菜单管理", icon = "fa fa-list", code = "menu", url = "/views/system/menu/menu", order = 3, page = true, parentCode = "system")
public class SysMenuController extends BaseController {

    @Resource
    private ISysMenuService menuService;

    @Resource
    private ISysUserService userService;

    @Resource
    private ISysRoleService roleService;


    /**
     * 获取菜单信息
     */
    @Permission
    @RequestMapping(value = "info", method = {RequestMethod.GET})
    @Menu(name = "获取菜单信息", code = "menu_info", parentCode = "menu")
    public Object info(Long menuId) {
        if (ToolUtil.isEmpty(menuId)) {
            throw new ServiceException("参数为空");
        }
        SysMenu menu = this.menuService.getById(menuId);

        //获取父级菜单的id
        SysMenu temp = new SysMenu();
        temp.setCode(menu.getPcode());
        SysMenu pMenu = this.menuService.getOne(new QueryWrapper<>(temp));

        //如果父级是顶级菜单
        if (pMenu == null) {
            menu.setPcode("0");
        } else {
            //设置父级菜单的code为父级菜单的id
            menu.setPcode(String.valueOf(pMenu.getId()));
        }

        Map<String, Object> menuMap = BeanUtil.beanToMap(menu);
        menuMap.put("pcodeName", menuService.getMenuNameByCode(temp.getCode()));
        return Result.createSuccess(menuMap);
    }

    /**
     * 编辑菜单
     */
    @Permission
    @RequestMapping(value = "/edit", method = {RequestMethod.POST})
    @Menu(name = "编辑菜单", code = "menu_edit", parentCode = "menu")
    public Object edit(@RequestBody SysMenu menu) {
        //设置父级菜单编号
        menuSetPcode(menu);

        this.menuService.updateById(menu);
        return Result.createSuccess();
    }

    /**
     * 查询菜单列表
     */
    @Permission
    @RequestMapping(value = "/list", method = {RequestMethod.POST})
    @Menu(name = "查询菜单列表", code = "menu_list", parentCode = "menu")
    public Object list(@RequestBody MenuQuery query) {
        List<SysMenu> menus = this.menuService.selectMenus(query.getMenuName(), query.getLevel());
        List<Map<String, Object>> mapList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(menus)) {
            menus.forEach(sysMenu -> {
                Map<String, Object> stringObjectMap = BeanUtil.beanToMap(sysMenu);
                wrapTheMap(stringObjectMap);
                mapList.add(stringObjectMap);
            });
        }
        Page<Map<String, Object>> mapPage = new PageFactory<Map<String, Object>>().create(query);
        mapPage.setRecords(mapList);
        return new PageInfo<>(mapPage);
    }

    protected void wrapTheMap(Map<String, Object> map) {
        map.put("isMenuName", YesOrNotEnum.valueOf((Integer) map.get("ismenu")));
    }

    /**
     * 添加菜单
     */
    @Permission
    @RequestMapping(value = "/add", method = {RequestMethod.POST})
    @Menu(name = "添加菜单", code = "menu_add", parentCode = "menu")
    public Object add(@RequestBody SysMenu menu) {
        //判断是否存在该编号
        String existedMenuName = menuService.getMenuNameByCode(menu.getCode());
        if (ToolUtil.isNotEmpty(existedMenuName)) {
            throw new ServiceException("编码已存在");
        }

        //设置父级菜单编号
        menuSetPcode(menu);

        menu.setStatus(MenuStatus.ENABLE.getCode());
        this.menuService.save(menu);
        List<SysMenu> list = this.menuService.list();
        String ids = "";
        if(CollUtil.isNotEmpty(list)) {
            List<Long> collect = list.stream().map(SysMenu::getId).collect(Collectors.toList());
            ids = CollUtil.join(collect, ",");
        }
        this.roleService.setAuthority(Integer.valueOf(Const.ADMIN_ROLE_ID), ids);
        return Result.createSuccess();
    }

    /**
     * 删除菜单
     */
    @Permission
    @RequestMapping(value = "/remove", method = {RequestMethod.GET})
    @Menu(name = "删除菜单", code = "menu_remove", parentCode = "menu")
    public Object remove(Long menuId) {
        if (ToolUtil.isEmpty(menuId)) {
            throw new ServiceException("参数为空");
        }
        this.menuService.delMenuContainSubMenus(menuId);
        List<SysMenu> list = this.menuService.list();
        String ids = "";
        if(CollUtil.isNotEmpty(list)) {
            List<Long> collect = list.stream().map(SysMenu::getId).collect(Collectors.toList());
            ids = CollUtil.join(collect, ",");
        }
        this.roleService.setAuthority(Integer.valueOf(Const.ADMIN_ROLE_ID), ids);
        return Result.createSuccess();
    }

    /**
     * 首页左侧树
     */
    @RequestMapping(value = "/menus", method = {RequestMethod.GET})
    @Permission
    @Menu(name = "首页左侧树", code = "menu_menus", parentCode = "menu")
    public Object menus() {
        String userId = getUserId();
        String roleid = userService.getById(userId).getRoleid();
        Integer[] roleArray = Convert.toIntArray(roleid);
        //获取菜单列表
        List<Integer> roleList = new ArrayList<>(Arrays.asList(roleArray));
        List<MenuNode> menus = menuService.getMenusByRoleIds(roleList);
        List<MenuNode> titles = MenuNode.buildTitle(menus);
        return Result.createSuccess(titles);
    }

    /**
     * 获取菜单列表(首页用)
     */
    @RequestMapping(value = "/menuTreeList", method = {RequestMethod.GET})
    @Permission
    @Menu(name = "获取菜单列表(首页用)", code = "menu_menuTreeList", parentCode = "menu")
    public Object menuTreeList() {
        return Result.createSuccess(this.menuService.menuTreeList());
    }

    /**
     * 获取菜单列表(选择父级菜单用)
     */
    @Permission
    @RequestMapping(value = "/selectMenuTreeList", method = {RequestMethod.GET})
    @Menu(name = "获取菜单列表(选择父级菜单用)", code = "menu_selectMenuTreeList", parentCode = "menu")
    public Object selectMenuTreeList() {
        List<ZTreeNode> roleTreeList = this.menuService.menuTreeList();
        roleTreeList.add(ZTreeNode.createParent());
        return Result.createSuccess(roleTreeList);
    }

    /**
     * 获取树形图的角色下所有菜单
     */
    @Permission
    @RequestMapping(value = "/menuTreeListByRoleId", method = {RequestMethod.GET})
    @Menu(name = "获取树形图的角色下所有菜单", code = "menu_menuTreeListByRoleId", parentCode = "menu")
    public Object menuTreeListByRoleId(Integer roleId) {
        List<Long> menuIds = this.menuService.getMenuIdsByRoleId(roleId);
        if (ToolUtil.isEmpty(menuIds)) {
            return Result.createSuccess(this.menuService.menuTreeList());
        } else {
            return Result.createSuccess(this.menuService.menuTreeListByMenuIds(menuIds));
        }
    }

    /**
     * 根据请求的父级菜单编号设置pcode和层级
     */
    private void menuSetPcode(SysMenu menu) {
        if (ToolUtil.isEmpty(menu.getPcode()) || menu.getPcode().equals("0")) {
            menu.setPcode("0");
            menu.setPcodes("[0],");
            menu.setLevels(1);
        } else {
            long code = Long.parseLong(menu.getPcode());
            SysMenu pMenu = menuService.getById(code);
            Integer pLevels = pMenu.getLevels();
            menu.setPcode(pMenu.getCode());

            //如果编号和父编号一致会导致无限递归
            if (menu.getCode().equals(menu.getPcode())) {
                throw new ServiceException("菜单无上级");
            }

            menu.setLevels(pLevels + 1);
            menu.setPcodes(pMenu.getPcodes() + "[" + pMenu.getCode() + "],");
        }
    }


}
